package androidlab.sprintingsquirrel.sharing;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Writer;
import java.util.UUID;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.widget.Toast;
import androidlab.sprintingsquirrel.ResourceManager;

public class SharingService {

	private static final String NAME = "SprintingSquirrel";
	private static final UUID MY_UUID = UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66");
	
	private BluetoothAdapter bluetoothAdapter;
	private AcceptThread acceptThread;
    private ConnectThread connectThread;
    private ConnectedThread connectedThread;

	public SharingService() {
		bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
	}
	
	public synchronized void start() {

        // Cancel any thread attempting to make a connection
        if (connectThread != null) {connectThread.cancel(); connectThread = null;}

        // Cancel any thread currently running a connection
        if (connectedThread != null) {connectedThread.cancel(); connectedThread = null;}

        // Start the thread to listen on a BluetoothServerSocket
        if (acceptThread == null) {
            acceptThread = new AcceptThread();
            acceptThread.start();
        }
    }
	
	public synchronized void connect(BluetoothDevice device) {
        // Cancel any thread attempting to make a connection
        if (connectThread != null) {connectThread.cancel(); connectThread = null;}

        // Cancel any thread currently running a connection
        if (connectedThread != null) {connectedThread.cancel(); connectedThread = null;}

        // Start the thread to connect with the given device
        connectThread = new ConnectThread(device);
        connectThread.start();
    }
	
	public synchronized void connected(BluetoothSocket socket, BluetoothDevice device) {
        connectedThread = new ConnectedThread(socket);
        connectedThread.start();
    }
	
	public synchronized void stop() {
        if (connectThread != null) {
            connectThread.cancel();
            connectThread = null;
        }

        if (connectedThread != null) {
            connectedThread.cancel();
            connectedThread = null;
        }

        if (acceptThread != null) {
            acceptThread.cancel();
            acceptThread = null;
        }
    }
	
	public void write(byte[] out) {
        ConnectedThread r;
        synchronized (this) {
            r = connectedThread;
        }
        if(r == null) {
        	ResourceManager.getInstance().activity.runOnUiThread(new Runnable() {

				@Override
				public void run() {
					Toast.makeText(ResourceManager.getInstance().activity, "Keine Verbindung!", Toast.LENGTH_SHORT).show();
				}
				
			});
        	return;
        }
        r.write(out);
    }
	
	private class AcceptThread extends Thread {
        private final BluetoothServerSocket mmServerSocket;

        public AcceptThread() {
            BluetoothServerSocket tmp = null;

            try {
            	tmp = bluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
            } catch (IOException e) {
                System.out.println("Failed");
            }
            mmServerSocket = tmp;
        }

        public void run() {
            BluetoothSocket socket = null;

            while (true) {
                try {
                	ResourceManager.getInstance().activity.runOnUiThread(new Runnable() {

						@Override
						public void run() {
							Toast.makeText(ResourceManager.getInstance().activity, "Warte auf Anfrage...", Toast.LENGTH_SHORT).show();
						}
						
					});
                    socket = mmServerSocket.accept();
                } catch (IOException e) {
                    System.out.println("accept() failed");
                    break;
                }

                if (socket != null) {
                    synchronized (SharingService.this) {
                        connected(socket, socket.getRemoteDevice());
                        break;
                    }
                }
            }

        }

        public void cancel() {
            try {
                mmServerSocket.close();
            } catch (IOException e) {
                System.out.println("close() of server failed");
            }
        }
    }

    private class ConnectThread extends Thread {
        private final BluetoothSocket mmSocket;
        private final BluetoothDevice mmDevice;

        public ConnectThread(BluetoothDevice device) {
            BluetoothSocket tmp = null;
            mmDevice = device;

            try {
            	tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
            } catch (IOException e) {
                System.out.println("create() failed");
            }
            mmSocket = tmp;
        }

        public void run() {
            bluetoothAdapter.cancelDiscovery();

            try {
                mmSocket.connect();
            } catch (IOException e) {
                try {
                    mmSocket.close();
                } catch (IOException e2) {
                    System.out.println("socket during connection failure");
                }
                return;
            }
            connected(mmSocket, mmDevice);
        }

        public void cancel() {
            try {
                mmSocket.close();
            } catch (IOException e) {
                System.out.println("socket failed");
            }
        }
    }

    private class ConnectedThread extends Thread {
        private final BluetoothSocket mmSocket;
        private final InputStream mmInStream;
        private final OutputStream mmOutStream;

        public ConnectedThread(BluetoothSocket socket) {
            mmSocket = socket;
            InputStream tmpIn = null;
            OutputStream tmpOut = null;

            try {
                tmpIn = socket.getInputStream();
                tmpOut = socket.getOutputStream();
            } catch (IOException e) {
                System.out.println("temp sockets not created");
            }

            mmInStream = tmpIn;
            mmOutStream = tmpOut;
        }

        public void run() {
        	ResourceManager.getInstance().activity.runOnUiThread(new Runnable() {

				@Override
				public void run() {
					Toast.makeText(ResourceManager.getInstance().activity, "Verbindung hergestellt.", Toast.LENGTH_SHORT).show();
				}
				
			});
            byte[] buffer = new byte[1024];
            int bytes;

            while (true) {
                try {
                    bytes = mmInStream.read(buffer);

                    String level = new String(buffer, 0, bytes);
                    BufferedReader br = new BufferedReader(new InputStreamReader(mmInStream));
                    Writer writer = new FileWriter(ResourceManager.getInstance().activity.getBaseContext().getFilesDir().getAbsolutePath() + File.separator + level);
                    while (true) {
                        String data = br.readLine();
                        if(data.equals("EOF")) {
                            writer.flush();
                        	writer.close();
                        	ResourceManager.getInstance().activity.runOnUiThread(new Runnable() {

                				@Override
                				public void run() {
                					Toast.makeText(ResourceManager.getInstance().activity, "Level erhalten.", Toast.LENGTH_SHORT).show();
                				}
                				
                			});
                        	break;
                        }
                        writer.write(data);
                        writer.write(System.getProperty("line.separator"));
                    }
                } catch (IOException e) {
                    System.out.println(e);
                    break;
                }
            }
        }

        public void write(byte[] bytes) {
            try {
                mmOutStream.write(bytes);
            } catch (IOException e) {
                System.out.println("Exception during write");
            }
        }

        public void cancel() {
            try {
                mmSocket.close();
            } catch (IOException e) {
                System.out.println("close() of connect socket failed");
            }
        }
    }
}
